#include "Delegate.h"
#ifndef DELEGATE_CPP_
#define DELEGATE_CPP_

template<typename ReturnType, typename ...ParamType>
IDelegate<ReturnType, ParamType...>::IDelegate()
{}

template<typename ReturnType, typename ...ParamType>
IDelegate<ReturnType, ParamType...>::~IDelegate()
{
    for (EventIterator it = events.begin(); it != events.end(); it++)
    {
        (*it).second = false;
        (*it).first->operator-=(this);
    }
}

template<typename ReturnType, typename ...ParamType>
bool IDelegate<ReturnType, ParamType...>::compare(IDelegate<ReturnType, ParamType...> *_delegate) const
{
    return true;
}

//普通函数/静态成员函数委托
template<typename ReturnType, typename ...ParamType>
CStaticDelegate<ReturnType, ParamType...>::CStaticDelegate(Func _func,void* _usrHandle) : m_Func(_func),m_UsrData(_usrHandle) 
{}

template<typename ReturnType, typename ...ParamType>
bool CStaticDelegate<ReturnType, ParamType...>::isType(const std::type_info& _type)
{
    return typeid(CStaticDelegate<ReturnType, ParamType...>) == _type;
}

template<typename ReturnType, typename ...ParamType>
ReturnType  CStaticDelegate<ReturnType, ParamType...>::invoke(ParamType ... params)
{ 
    //if (m_Func!=nullptr)
    return m_Func(params...,m_UsrData);
}

template<typename ReturnType, typename ...ParamType>
bool CStaticDelegate<ReturnType, ParamType...>::compare(IDelegate<ReturnType, ParamType ...> *_delegate)const
{
    if (nullptr == _delegate || !_delegate->isType(typeid(CStaticDelegate<ReturnType, ParamType ...>))) return false;
    CStaticDelegate<ReturnType, ParamType ...> * cast = static_cast<CStaticDelegate<ReturnType, ParamType ...>*>(_delegate);
    return cast->m_Func == m_Func;
}

template<typename ReturnType, typename ...ParamType>
CStaticDelegate<ReturnType, ParamType...>::~CStaticDelegate()
{}

//成员函数委托
template<typename T, typename ReturnType, typename ...ParamType>
CMethodDelegate<T, ReturnType, ParamType...>::CMethodDelegate(T * _object, Method _method) : m_Object(_object), m_Method(_method)
{}

template<typename T, typename ReturnType, typename ...ParamType>
bool CMethodDelegate<T, ReturnType, ParamType...>::isType(const std::type_info& _type)
{ 
    return typeid(CMethodDelegate<T, ReturnType, ParamType...>) == _type;
}

template<typename T, typename ReturnType, typename ...ParamType>
ReturnType CMethodDelegate<T, ReturnType, ParamType...>::invoke(ParamType...params)
{
    return (m_Object->*m_Method)(params...);
}

template<typename T, typename ReturnType, typename ...ParamType>
bool CMethodDelegate<T, ReturnType, ParamType...>::compare(IDelegate<ReturnType, ParamType...> *_delegate) const
{
    if (0 == _delegate || !_delegate->isType(typeid(CMethodDelegate<T, ReturnType, ParamType...>))) return false;
    CMethodDelegate<T, ReturnType, ParamType...>* cast = static_cast<CMethodDelegate<T, ReturnType, ParamType...>*>(_delegate);
    return cast->m_Object == m_Object && cast->m_Method == m_Method;
}

template<typename T, typename ReturnType, typename ...ParamType>
CMethodDelegate<T, ReturnType, ParamType...>::CMethodDelegate()
{}

template<typename T, typename ReturnType, typename ...ParamType>
CMethodDelegate<T, ReturnType, ParamType...>::~CMethodDelegate()
{}


//可调用对象委托
template<typename ReturnType, typename ...ParamType>
CallableMeta<ReturnType, ParamType...>::CallableMeta(std::function<ReturnType(ParamType...)> _caller) :m_caller(_caller)
{}

template<typename ReturnType, typename ...ParamType>
CallableMeta<ReturnType, ParamType...>::~CallableMeta()
{}

template<typename ReturnType, typename ...ParamType>
bool CallableMeta<ReturnType, ParamType...>::isType(const std::type_info& _type)
{
    return typeid(CallableMeta<ReturnType, ParamType...>) == _type;
}

template<typename ReturnType, typename ...ParamType>
ReturnType  CallableMeta<ReturnType, ParamType...>::invoke(ParamType ... params)
{
    if (m_caller.operator bool())
    {
        return m_caller(params...);
    }
    return ReturnType();
}

template<typename ReturnType, typename ...ParamType>
bool CallableMeta<ReturnType, ParamType...>::compare(IDelegate<ReturnType, ParamType ...> *_delegate)const
{
    if (nullptr == _delegate)
    {
        return false;
    }
    if (_delegate->isType(typeid(CallableMeta<ReturnType, ParamType...>)) == false)
    {
        return false;
    }
    CallableMeta<ReturnType, ParamType ...> * cast = static_cast<CallableMeta<ReturnType, ParamType ...>*>(_delegate);
    bool eq = *(cast->m_caller.target<ReturnType(*)(ParamType...)>()) == *(m_caller.target<ReturnType(*)(ParamType...)>());
    return eq;
}

//事件
template<typename ReturnType, typename ...ParamType>
HKEvent<ReturnType,ParamType...>::HKEvent() 
{}

template<typename ReturnType, typename ...ParamType>
HKEvent<ReturnType, ParamType...>::~HKEvent() 
{ 
    clear();
}

template<typename ReturnType, typename ...ParamType>
bool HKEvent<ReturnType, ParamType...>::isEmpty() const
{
    for (ConstListDelegateIterator iter = m_ListDelegates.begin(); iter != m_ListDelegates.end(); ++iter)
    {
        if ((*iter)==nullptr) return false;
    }
    return true;
}

template<typename ReturnType, typename ...ParamType>
void HKEvent<ReturnType, ParamType...>::clear()
{
    for (ListDelegateIterator iter = m_ListDelegates.begin(); iter != m_ListDelegates.end(); ++iter)
    {
        if ((*iter)!=nullptr)
        {
            if ((*iter)->events[this] == true)
            {
                if ((*iter)->count < 2)
                    delete (*iter);
                else
                    (*iter)->count--;
            }
            (*iter) = nullptr;
        }
    }
    m_ListDelegates.clear();
}

template<typename ReturnType, typename ...ParamType>
HKEvent<ReturnType, ParamType...>& HKEvent<ReturnType, ParamType...>::operator+=(IDelegate<ReturnType, ParamType...>* _delegate)
{
    for (ListDelegateIterator iter = m_ListDelegates.begin(); iter != m_ListDelegates.end(); ++iter)
    {
        if ((*iter) != nullptr && ((*iter) == _delegate))
        {
            return *this;   //避免同一个委托对象被注册两次
        }
    }
    _delegate->events[this] = true;
    _delegate->count++;
    m_ListDelegates.push_back(_delegate);
    return *this;
}

template<typename ReturnType, typename ...ParamType>
HKEvent<ReturnType, ParamType...>& HKEvent<ReturnType, ParamType...>::operator-=(IDelegate<ReturnType, ParamType...>* _delegate)
{
    for (ListDelegateIterator iter = m_ListDelegates.begin(); iter != m_ListDelegates.end(); ++iter)
    {
        //注销委托时必须指定到具体的委托对象
        if ((*iter) != nullptr && (*iter) == _delegate)
        {
            if ((*iter)->events[this] == true)
            {
                if ((*iter)->count < 2)
                    delete (*iter);
                else
                    (*iter)->count--;
            }
            (*iter) = nullptr;
            break;
        }
    }
    return *this;
}

template<typename ReturnType, typename ...ParamType>
std::vector<ReturnType> HKEvent<ReturnType, ParamType...>::operator()(ParamType... params)
{
    ListDelegateIterator iter = m_ListDelegates.begin();
    std::vector<ReturnType> _Results;
    while (iter != m_ListDelegates.end())
    {
        if (nullptr == (*iter))
        {
            iter = m_ListDelegates.erase(iter);
        }
        else
        {
            if ((*iter)->events[this] == true)
                _Results.push_back((*iter)->invoke(params...));
            ++iter;
        }
    }
    return _Results;
}


template< typename ...ParamType>
HKEvent<void, ParamType...>::HKEvent() 
{}

template< typename ...ParamType>
HKEvent<void, ParamType...>::~HKEvent()
{
    clear(); 
}

template< typename ...ParamType>
bool HKEvent<void, ParamType...>::isEmpty() const
{
    for (ConstListDelegateIterator iter = m_ListDelegates.begin(); iter != m_ListDelegates.end(); ++iter)
    {
        if ((*iter)!=nullptr) return false;
    }
    return true;
}

template< typename ...ParamType>
void HKEvent<void, ParamType...>::clear()
{
    for (ListDelegateIterator iter = m_ListDelegates.begin(); iter != m_ListDelegates.end(); ++iter)
    {
        if ((*iter)!=nullptr)
        {
            if ((*iter)->events[this] == true)
            {
                if ((*iter)->count < 2)
                    delete (*iter);
                else
                    (*iter)->count--;
            }
            (*iter) = nullptr;
        }
    }
    m_ListDelegates.clear();
}

template< typename ...ParamType>
HKEvent<void, ParamType...>& HKEvent<void, ParamType...>::operator+=(IDelegate<void, ParamType...>* _delegate)
{
    for (ListDelegateIterator iter = m_ListDelegates.begin(); iter != m_ListDelegates.end(); ++iter)
    {
        if ((*iter) != nullptr && (*iter)->compare(_delegate)&& ((*iter) == _delegate))
        {
            return *this;    //避免同一个委托对象被注册两次
        }
    }
    _delegate->events[this] = true;
    _delegate->count++;
    m_ListDelegates.push_back(_delegate);
    return *this;
}

template< typename ...ParamType>
HKEvent<void, ParamType...>& HKEvent<void, ParamType...>::operator-=(IDelegate<void, ParamType...>* _delegate)
{
    for (ListDelegateIterator iter = m_ListDelegates.begin(); iter != m_ListDelegates.end(); ++iter)
    {
        //注销委托时必须指定到具体的委托对象(*iter指针多态性信息可能失效，导致调用到基类IDelegate的compare,因此可以不做类型校验).
        if ((*iter) != nullptr /*&& (*iter)->compare(_delegate)*/ && ((*iter) == _delegate))
        {
            if ((*iter)->events[this] == true)
            {
                if ((*iter)->count < 2)
                    delete (*iter);
                else
                    (*iter)->count--;
            }
            (*iter) = nullptr;
            break;
        }
    }
    return *this;
}

template< typename ...ParamType>
void HKEvent<void, ParamType...>::operator()(ParamType... params)
{
    ListDelegateIterator iter = m_ListDelegates.begin();
    while (iter != m_ListDelegates.end())
    {
        if (nullptr == (*iter))
        {
            iter = m_ListDelegates.erase(iter);
        }
        else
        {
            if ((*iter)->events[this] == true)
                (*iter)->invoke(params...);
            ++iter;
        }
    }
}

#endif
